using Cysharp.Threading.Tasks;
using IQIGame.Onigao.Framework;
using IQIGame.Onigao.Game;
using System;
using System.Collections.Generic;
using System.Linq;
using static IQIGame.Onigao.GamePlay.UIN_CommonEquipTips;

namespace IQIGame.Onigao.GamePlay
{
    public class UIN_HeroEquipSelectedInfo : UIBaseNode
    {
        #region Template Generate,don't modify
        protected class UIB_UIN_HeroEquipSelectedInfo
        {
            #region ObjectBinding Generate
            public UnityEngine.UI.ExLoopVerticalScrollRect loopVerticalScrollRect { protected set; get; }
            public UnityEngine.GameObject emptyScroll { protected set; get; }
            public IQIGame.Onigao.Framework.ExButton buttonSort { protected set; get; }
            public IQIGame.Onigao.Framework.ExButton buttonScreen { protected set; get; }
            public IQIGame.Onigao.Framework.ExButton buttonClose { protected set; get; }
            public UnityEngine.GameObject equipTipsCompare { protected set; get; }
            public UnityEngine.GameObject equipTipsCurrent { protected set; get; }
            public IQIGame.Onigao.Framework.ExButton btnFilterClear { protected set; get; }
            public IQIGame.Onigao.Framework.ExButton buttonCloseEquipTips { protected set; get; }
            public virtual void InitBinding(ObjectBinding __binding)
            {
                __binding.TryGetVariableValue<UnityEngine.UI.ExLoopVerticalScrollRect>("loopVerticalScrollRect", out var __tbv0);
                this.loopVerticalScrollRect = __tbv0;
                __binding.TryGetVariableValue<UnityEngine.GameObject>("emptyScroll", out var __tbv1);
                this.emptyScroll = __tbv1;
                __binding.TryGetVariableValue<IQIGame.Onigao.Framework.ExButton>("buttonSort", out var __tbv2);
                this.buttonSort = __tbv2;
                __binding.TryGetVariableValue<IQIGame.Onigao.Framework.ExButton>("buttonScreen", out var __tbv3);
                this.buttonScreen = __tbv3;
                __binding.TryGetVariableValue<IQIGame.Onigao.Framework.ExButton>("buttonClose", out var __tbv4);
                this.buttonClose = __tbv4;
                __binding.TryGetVariableValue<UnityEngine.GameObject>("equipTipsCompare", out var __tbv5);
                this.equipTipsCompare = __tbv5;
                __binding.TryGetVariableValue<UnityEngine.GameObject>("equipTipsCurrent", out var __tbv6);
                this.equipTipsCurrent = __tbv6;
                __binding.TryGetVariableValue<IQIGame.Onigao.Framework.ExButton>("btnFilterClear", out var __tbv7);
                this.btnFilterClear = __tbv7;
                __binding.TryGetVariableValue<IQIGame.Onigao.Framework.ExButton>("buttonCloseEquipTips", out var __tbv8);
                this.buttonCloseEquipTips = __tbv8;
            }
            #endregion ObjectBinding Generate 
        }
        #endregion Template Generate,don't modify


        #region fields
        private LoopScrollAdapter<UIN_OneItem> equipItems = null;
        private UIN_CommonEquipTips currTip = null;
        private UIN_CommonEquipTips compareTip = null;

        private EquipFilter filter = EquipFilter.Default;
        private EquipSort sort = EquipSort.Default;

        private HeroData heroData = null;
        private int equipColumn = -1;
        private ItemEquipmentData equipColumnItem = null;
        private List<ItemEquipmentData> listEquipData = null;
        private List<ItemEquipmentData> listCurrEquipData = null;
        private int selectedEquipIndex = -1;
        private long selectedEquipId = -1;
        #endregion fields

        #region properties
        protected UIB_UIN_HeroEquipSelectedInfo ui { get; set; }
        protected UIMsgDispatcher uiMsgDispatcher => this._msgDispatcher as UIMsgDispatcher;

        #endregion properties

        protected override void BeforeInit()
        {
            ui = new UIB_UIN_HeroEquipSelectedInfo();
            ui.InitBinding(this.csObjBind);
        }

        protected override void OnInit()
        {
            this.equipItems = this.InitLoopScroll<UIN_OneItem>(this.ui.loopVerticalScrollRect, this.OnEquipItemChanged);
            this.equipItems.InitUnitSelected(UnitSelectType.ByExButton, this.OnEquipItemSelected);

            this.currTip = this.InitChildNode<UIN_CommonEquipTips>(this.ui.equipTipsCurrent);
            this.compareTip = this.InitChildNode<UIN_CommonEquipTips>(this.ui.equipTipsCompare);

            this.HideUnit();
        }

        protected override void OnShow()
        {

        }

        protected override void OnHide()
        {
            this.HideUnit();
            this.ClearData();
        }

        /// <summary>
        /// 添加UGUI侦听
        /// </summary>
        protected override void AddUGUIListener()
        {
            this.ui.buttonClose.onClick.AddListener(this.OnClickClose);
            this.ui.buttonScreen.onClick.AddListener(this.OnClickScreenFilter);
            this.ui.btnFilterClear.onClick.AddListener(this.OnClickClearScreenFilter);
            this.ui.buttonSort.onClick.AddListener(this.OnClickSort);
            this.ui.buttonCloseEquipTips.onClick.AddListener(this.HideTipPanels);
        }

        /// <summary>
        /// 添加全局侦听（MsgDispatcher）
        /// </summary>
        protected override void AddMsgListeners()
        {
            this.uiMsgDispatcher.AddListener<EquipSort>(MsgEventType.EquipSort, this.OnMsgSort);
            this.uiMsgDispatcher.AddListener<EquipFilter>(MsgEventType.EquipFilter, this.OnMsgFilter);
        }

        protected override void OnDispose()
        {
            this.ClearData();
        }

        #region methonds

        private void OnClickClose()
        {
            var parentUnit = this.GetParentUnit();
            this.Hide();
            parentUnit?.RefreshWhenCloseSelectedPanel();
        }

        private UIN_HeroEquip GetParentUnit()
        {
            return this.parentNode as UIN_HeroEquip;
        }

        private void OnClickScreenFilter()
        {
            this.OpenUI<UIEquipListScreen>(UD_EquipListCreen.Create(this.filter));
        }

        private void OnClickClearScreenFilter()
        {
            this.RefreshFilterState(EquipFilter.Default);
        }

        private void OnClickSort()
        {
            this.OpenUI<UIEquipListSort>(UD_EquipListSort.Create(this.sort));
        }

        private void OnMsgSort(EquipSort sort)
        {
            if (this.sort == sort)
                return;
            this.sort.Sync(sort);
            this.ShowWarehouse(true);
        }

        private void OnMsgFilter(EquipFilter filter)
        {
            this.RefreshFilterState(filter);
        }

        private void RefreshFilterState(EquipFilter filter)
        {
            if (this.filter == filter)
                return;
            this.filter.Sync(filter);
            this.ShowWarehouse(true);
        }

        private void HideUnit()
        {
            this.HideTipPanels();
        }

        private void HideTipPanels()
        {
            this.currTip.Hide();
            this.compareTip.Hide();
        }

        public void Show(HeroData heroData, int column, long selectedEquipId)
        {
            this.Show();
            this.SetData(heroData, column, selectedEquipId);
            this.ShowWarehouse();
        }

        private void ClearData()
        {
            this.filter = EquipFilter.Default;
            this.sort = EquipSort.Default;

            this.heroData = null;
            this.equipColumn = -1;
            this.equipColumnItem = null;
            this.listEquipData = null;
            this.listCurrEquipData = null;
            this.SetListSelectedData(-1);
        }

        private void SetData(HeroData data, int column, long selectedEquipId)
        {
            this.heroData = data;
            this.equipColumn = column;
            this.SetListSelectedData(selectedEquipId);

            this.RefreshEquipColumnItem();
            this.listEquipData = this.GetStatisticsCanWearsEquips();
        }

        private void SetListSelectedData(long selectedEquipId, int selectedEquipIndex = -1)
        {
            this.selectedEquipId = selectedEquipId;
            this.selectedEquipIndex = selectedEquipIndex;
        }

        private void RefreshEquipColumnItem()
        {
            this.equipColumnItem = this.heroData.GetWearEquipItem(this.equipColumn);
        }

        private List<ItemEquipmentData> GetStatisticsCanWearsEquips()
        {
            return GameDataCenter.PlayerData.item.GetEquipList(this.IsHeroCanWearEquips);
        }

        private bool IsHeroCanWearEquips(ItemEquipmentData equipItem)
        {
            var wearableHeroClass = equipItem.cfgData.WearableHeroClass;
            return wearableHeroClass.Contains(this.heroData.cfgData.HeroClass);
        }

        private void ShowWarehouse(bool isMsgFitlerOrSort = false)
        {
            this.FitlerAndSortDatalist(this.listEquipData);
            this.ShowListState(isMsgFitlerOrSort);
            this.ShowBtnClearFilter();
        }

        private void FitlerAndSortDatalist(List<ItemEquipmentData> listOrg)
        {
            this.FitlerDatalist(listOrg);
            this.SortDataList();
        }

        private void FitlerDatalist(List<ItemEquipmentData> listOrg)
        {
            this.ClearFitlerDataList();
            this.listCurrEquipData = ItemModule.Instance.LeachEquipList(listOrg, this.filter);
        }

        private void ClearFitlerDataList()
        {
            this.listCurrEquipData?.Clear();
        }

        private void SortDataList()
        {
            ItemModule.Instance.ReorderEquipList(this.listCurrEquipData, this.sort, this.WearSort);
        }

        private int WearSort(ItemData a, ItemData b)
        {
            var wearerA = a.currWearer;
            var wearerB = b.currWearer;
            if (wearerA == this.heroData && wearerB != this.heroData)
                return -1;
            if (wearerA != this.heroData && wearerB == this.heroData)
                return 1;
            return 0;
        }

        private void ShowListState(bool isNoSelected)
        {
            int cnt = this.listCurrEquipData.Count;
            int index = this.GetSelectedEquipListIndex(this.listCurrEquipData, isNoSelected);
            this.equipItems.RefillCellsAndSelected(cnt, index);
            this.ui.emptyScroll.SetActive(cnt == 0);
        }

        private int GetSelectedEquipListIndex(List<ItemEquipmentData> list, bool isNoSelected)
        {
            if (isNoSelected)
            {
                return -1;
            }
            long equipId = this.selectedEquipId;
            if (equipId < 0 && this.heroData.equips.TryGetValue(this.equipColumn, out var columnEquipId))
            {
                equipId = columnEquipId;
            }
            return equipId <= 0 ? -1 : this.GetEquipListIndex(list, equipId);
        }

        private int GetEquipListIndex(List<ItemEquipmentData> list, long equipId)
        {
            for (int i = 0, cnt = list.Count; i < cnt; i++)
            {
                var equip = list[i];
                if (equip.id == equipId)
                {
                    return i;
                }
            }
            return -1;
        }

        private void OnEquipItemChanged(UIN_OneItem item, int index)
        {
            ItemEquipmentData equipItem = this.listCurrEquipData[index];
            item.ShowEquip(equipItem, this.heroData, this.equipColumn);
            item.SetSelected(this.selectedEquipId == equipItem.id);
        }

        private void OnEquipItemSelected(int index, UIN_OneItem item)
        {
            var itemLast = this.equipItems.GetTEntity(this.selectedEquipIndex);
            itemLast?.SetSelected(false);
            this.SetListSelectedData(-1);
            this.HideTipPanels();
            if (item == null)
            {
                return;
            }
            ItemEquipmentData equipItem = this.listCurrEquipData[index];
            if (IsSameCidEquip(equipItem))
            {
                NoticeModule.ShowNoticeNoCall(APIUIHeroInfo.NoticeCid_SameCidEquip);
                return;
            }
            item.SetSelected(true);

            this.SetListSelectedData(equipItem.id, index);
            this.ShowTipCompare(equipItem);
            this.ShowTipCurrent(equipItem);
        }

        private bool IsSameCidEquip(ItemEquipmentData equipItem)
        {
            if (this.equipColumnItem != null && this.equipColumnItem.cid == equipItem.cid)
                return false;
            int equipColumn = this.heroData.GetWearSameCidEquipColumn(equipItem);
            if (equipColumn == -1)
                return false;

            var wearEquip = this.heroData.GetWearEquipItem(equipColumn);
            return (wearEquip != equipItem);
        }

        private void ShowTipCurrent(ItemEquipmentData equipItem)
        {
            this.currTip.ShowEquipWear(equipItem, this.heroData, this.equipColumnItem, this.OnClickEquipPanelBtn);
        }

        private void OnClickEquipPanelBtn(EquipTipBtnType btnType, ItemEquipmentData equipItem)
        {
            switch (btnType)
            {
                case EquipTipBtnType.Strengthen:
                    this.OpenEquipInfo(equipItem);
                    break;
                case EquipTipBtnType.Wear:
                    this.DoWear(equipItem);
                    break;
                case EquipTipBtnType.TakeOff:
                    this.SendWear(0).Forget();
                    break;
                default:
                    break;
            }
        }

        private void OpenEquipInfo(ItemEquipmentData equipItem)
        {
            UD_EquipInfo udEquip = UD_EquipInfo.NewFromPool();
            udEquip.Sync(UIEquipInfoTabType.UpLv, equipItem, null);
            this.OpenUI<UIEquipInfo>(udEquip);
        }

        private void DoWear(ItemEquipmentData equipItem)
        {
            var wearer = equipItem.currWearer;
            long equipId = equipItem.id;
            if (wearer != null && wearer != this.heroData)
            {
                string otherHeroName = HeroModule.Instance.GetHeroName(wearer);
                string currHeroName = HeroModule.Instance.GetHeroName(this.heroData);
                NoticeModule.ShowNotice(APIUIHeroInfo.NoticeCid_WearOtherHeroEquip, () =>
                {
                    this.SendWear(equipId).Forget();
                }, null, null, otherHeroName, equipItem.cfgData.Name, currHeroName);
            }
            else
            {
                this.SendWear(equipId).Forget();
            }
        }

        // equipId = 0 标识脱下
        private async UniTaskVoid SendWear(long equipId)
        {
            var result = await HeroModule.NetCore.CS_wearEquip(this.heroData.cid, this.equipColumn, equipId);
            if (result.IsSuccess)
            {
                HeroModule.Instance.UpHeroByPOD(result.heroPOD);

                if (this.isActive)
                {
                    this.RefreshAfterResponse(equipId);
                }
            }
        }

        private void RefreshAfterResponse(long equipId)
        {
            this.RefreshEquipColumnItem();
            this.SortDataList();
            int index = this.GetEquipListIndex(this.listCurrEquipData, equipId);
            this.equipItems.RefillCellsAndSelected(this.listCurrEquipData.Count, index);
            var parentUnit = this.GetParentUnit();
            parentUnit?.RefreshCurrEquipView();
            if (equipId > 0)
                this.HideTipPanels();
        }

        private void ShowTipCompare(ItemEquipmentData equipItem)
        {
            bool isShowCompare = this.equipColumnItem != null && equipItem != this.equipColumnItem;
            if (!isShowCompare)
            {
                this.compareTip.Hide();
                return;
            }
            this.compareTip.ShowEquipWear(this.equipColumnItem, this.heroData);
        }

        private void ShowBtnClearFilter()
        {
            bool isActive = this.filter != EquipFilter.Default;
            this.ui.btnFilterClear.SetActive(isActive);
        }
        #endregion methonds
    }
}
